/*
 * cache.h
 *
 *  Created on: Nov 19, 2013
 *      Author: adijoshi
 */
/* -------------------------------------------------------------------------------------------------
 File - cache.h
 Type - header file
 Contents -
 	 This file contains Macro declarations, function declarations, structure declarations
 	 and few global variable declarations.

Macros -
	1) Configurable parameters for cache -
		ADDRESS_LINES --> Number of bits used for specifying an address in trace file.
		SETS --> Number of sets in L2 cache.
		WAYS --> Number of ways in L2 cache i.e. associativity of L2 cache.
		BYTES_PER_LINE --> Number of bytes in a cache line.
		GET_SNOOP_MASK --> Integer used for masking in get_Snoop_Result() function.

	2) Input and output file names -
		INPUT_FILE_NAME --> file name(with format) for input trace file
		OUTPUT_FILE_NAME --> file name(with format) to which output is redirected

	3) OUTPUT_ON_CONSOLE - A switch to enable or disable printing on console
			if 1 --> intermediate bus operations are printed on console.
			if 0 --> intermediate bus operations are not printed on console, instead they are redirected to a
					text file named OUTPUT_FILE_NAME

	4) Trace file Access Type i.e. 'n' -
		CPU_READ_D --> n=0 i.e. read request from L1 data cache.
		CPU_WRITE_D --> n=1 i.e. write request from L1 data cache.
		CPU_READ_I --> n=2 i.e. read request from L1 instruction cache.
		SNOOPED_INVALIDATE --> n=3 i.e. snooped invalidate command.
		SNOOPED_READ --> n=4 i.e. snooped read request.
		SNOOPED_WRITE --> n=5 i.e. snooped write request.
		SNOOPED_RFO --> n=6 i.e. snooped read with intent to modify.
		CLEAR_CACHE --> n=8 i.e. clear the cache and reset all state.
		PRINT_CACHE --> n=9 i.e. print contents and state of each valid cache line.

	5)	Result of get_Snoop_Result() -
		SNOOPED_MISS --> 0
		SNOOPED_HIT --> 1
		SNOOPED_HITM --> 2

Global variables -
	1) TAG_BITS --> number of tag bits
	2) INDEX_BITS --> number of index bits
	3) BYTE_OFFSET --> number of byte offset
	4) cacheHit --> number of cache hits
	5) cacheMiss --> number of cache misses
	6) cacheRead --> number of cache reads
	7) cacheWrite --> number of cache writes
	8) memRead --> number of memory reads
	9) memWrite --> number of memory writes
 ------------------------------------------------------------------------------------------------- */

#ifndef CACHE_H_
#define CACHE_H_

#define ADDRESS_LINES 32
#define SETS 16384
#define WAYS 8
#define BYTES_PER_LINE 64				// in bytes
#define OUTPUT_ON_CONSOLE 1				// 1 - print on console, 0 - send to text file
#define GET_SNOOP_MASK 3
#define INPUT_FILE_NAME "test_input.txt"
#define OUTPUT_FILE_NAME "test_output.txt"

#define CPU_READ_D 0
#define CPU_WRITE_D 1
#define CPU_READ_I 2
#define SNOOPED_INVALIDATE 3
#define SNOOPED_READ 4
#define SNOOPED_WRITE 5
#define SNOOPED_RFO 6
#define CLEAR_CACHE 8
#define PRINT_CACHE 9

#define SNOOPED_MISS 0
#define SNOOPED_HIT 1
#define SNOOPED_HITM 2

unsigned int TAG_BITS,INDEX_BITS,BYTE_OFFSET;
int cacheHit,cacheMiss,cacheRead,cacheWrite,memRead,memWrite;

typedef struct CacheLineStruct{
	int Tag;
	int LRU_Status;
	int MESI_Status;
} CacheLine;

typedef enum LineStatusEnum{
	Modified,
	Exclusive,
	Shared,
	Invalid
	//STATE_MODIFIED,
	//STATE_EXCLUSIVE,
	//STATE_SHARED,
	//STATE_INVALID
} LineStatus;

CacheLine L2Cache[SETS][WAYS];

void init_Cache();
void exec_Read_Req(unsigned int operation,unsigned int address);
void exec_Write_Req(unsigned int operation,unsigned int address);
void print_Output(char* operation, unsigned int address,int printSwitch);
int match_Tag(int set,unsigned int address);
int get_Snoop_Result(char operation,unsigned int address);
void put_Snoop_Result(char operation,unsigned int address);
int fill_Cache_Line(int set,unsigned int address);
void update_MESI(unsigned int operation, int snoopResult, int set, int way);
void update_LRU(int set, int way);
int find_LRU_way(int set);
void alert_L1(int set,int way, char operation);
void read_From_DRAM(unsigned int address);
void write_To_DRAM(unsigned int address);

#endif /* CACHE_H_ */
